# coding=utf-8
from datetime import datetime
from flask import g, current_app
from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from comment.modules.user import User
from comment.modules.debt_info import Debt_info
from comment.modules.debt_repay import Debtor_repay
from comment.ultils.Financlal_Readlis import fr
from comment.ultils.decorators import Login_required
from comment.modules.loanApply import Loan
from comment.modules import db
from financial.resorces.transaction.const import LoanConfig
from financial.resorces.transaction.serializer import  LoanPaginateSerializer
from comment.ultils.gen_trans_id import gen_trans_id
from datetime import timedelta #timedelta时间相加相减的操作（days, seconds, microseconds,milliseconds, minutes, hours, weeks）
from dateutil.relativedelta import relativedelta #relativedelta也是时间上的操作（Year，Month，Day，Hours，Minutes，Seconds，Microseconds）
from decimal import Decimal

class LoanApply(Resource):
    '''借款的资源类'''

    '''拦截器看用户有没有登录过'''
    # 拦截器他会在LoginOut的所有的视图函数都会在执行视图函数之前，做一下装饰器的拦截
    method_decorators = [Login_required]  # 使用了登录拦截的装饰器

    def post(self):
        '''申请借款'''
        rp = RequestParser()

        rp.add_argument('holder',required=True) #借款人
        rp.add_argument('amount',required=True) #金额
        rp.add_argument('code',required=True) #验证码
        rp.add_argument('loanMonth',required=True) #还款期数

        args = rp.parse_args()

        holder = args.holder
        amout = args.amount
        loan_month = args.loanMonth
        code = args.code

        user_id = g.user_id
        cur_user = User.query.filter(User.id == user_id).first()

        username = cur_user.username

        #验证验证码，判断是否正确
        # 从Redis数据库中获取之前的验证码
        try:
            real_code = fr.get('registerCode:{}'.format(cur_user.phone))
            if not real_code or real_code.decode() != code:  # 数据库中没有code的，或者存储的code和参数不一致（有可能是错误或者过期了）
                current_app.logger.info("验证码错误或者失效")
                return {'message': '验证码错误或者失效', 'code': 203}
        except Exception as e:
            current_app.logger.error(e)
            return {
                'message': '验证码判断的时候，数据库连接错误',
                'code': 214
            }

        #LoanNum借款金额  lUid用户id  duration借款时长  loanNum借款金额  lRate年利率
        loan_apply =Loan(
            loanNum=amout,
            lUid=user_id,
            duration=loan_month,
            lName=username,
            lRate=LoanConfig.YEAR_RATE.value,
            lRepayDay=datetime.now().day
        )
        db.session.add(loan_apply)
        db.session.commit()
        return {'msg':'success'}

    def get(self):
        '''管理员看到的借款列表'''
        rp = RequestParser()

        rp.add_argument('start') #开始时间
        rp.add_argument('end') #结束时间
        rp.add_argument('curPage') #当前页
        rp.add_argument('perPage')  #每页数量
        rp.add_argument('approve_status') #审批状态

        args = rp.parse_args()

        start = args.get('start')
        end = args.get('end')
        cur_page = int(args.get('curPage'))
        per_page = int(args.get('perPage'))
        status = int(args.get('approve_status'))

        #过滤查询
        #第一个过滤条件
        if status > 0:
            loan_list = Loan.query.filter(Loan.status > 0)
        else:
            loan_list = Loan.query.filter(Loan.status == status)

        #第二个过滤条件
        if start and end:
            #需要根据起始和结束时间来过滤
            #cast将数据库的类型进行转化，后面转化类型（Loan.status转成DATE，Loan.applyDate一样）
            #paginate分页
            loan_list = loan_list.filter(db.cast(Loan.status,db.DATE) >= db.cast(Loan.applyDate,db.DATE))\
                .filter(db.cast(Loan.applyDate,db.DATE) <= db.cast(end,db.DATE))\
                .paginate(cur_page,per_page,error_out=False)
        else:
            loan_list = loan_list.paginate(cur_page,per_page,error_out=False)

        #分页数据的序列化
        data = LoanPaginateSerializer(loan_list).to_dict()
        return {
            'msg':'sucess',
            'data':data
        }

    def put(self):
        '''审批借款功能'''
        '''修改借款的状态，产生债权，创建还款计划'''
        rp = RequestParser()

        rp.add_argument('applyId')  # 借款申请ID
        rp.add_argument('status')  # 借款状态

        args = rp.parse_args()

        loan_id = args.get('applyId')
        status = args.get('status')

        #查询借款的对象
        loan = Loan.query.filter(Loan.id == loan_id).first()
        #第一步：更新借款申请状态
        loan.status = int(status) #修改属性
        print(loan.status)

        #第二步：创建债权（产生债权数据）
        if status == '1': #如果等于1表示通过
            debt_no = gen_trans_id('debt') #债权的编号
            debtors_id = loan.user.idNum #身份证号码
            #还款的最后时间
            end_date = datetime.now() + relativedelta(months=loan.duration) #months只要计算时间差都是加s的
            #创建债权
            new_debt = Debt_info(debtNo=debt_no, debtorsName=loan.lName, loanNo=loan.id,borrowerId=loan.lUid,
                                debtorsId=debtors_id, loanStartDate=datetime.now(), loanPeriod=loan.duration,
                                loanEndDate=end_date, repaymentStyle=loan.lRepayType, matchedMoney=0,
                                repaymenDate=loan.lRepayDay, repaymenMoney=loan.loanNum, matchedStatus=0,
                                debtMoney=loan.loanNum, debtYearRate=loan.lRate, debtTransferredMoney=0)
            db.session.add(new_debt)
            db.session.flush() #根据数据库主键的自增机制来生成一个新的主键值，把数据放在缓存里面去
            # 第三步：创建还款计划
            self.create_repay_list(new_debt) #调用还款计划
        #一次性提交事务
        db.session.commit()
        return {'msg': 'sucess'}

    #创建还款计划
    def  create_repay_list(self,new_debt):
        '''创建当前债权的坏款计划'''

        #月还款本金：借款的金额 / 借款的期数
        mount_cost = round(new_debt.repaymenMoney / new_debt.loanPeriod,2) #round做小数的转化，在最后面传保留几位小数就行了

        #月利息：年利率 / 12 （拿YEAR_RATE的value也就是0.055）
        mount_rate = round(LoanConfig.YEAR_RATE.value / 12,4)

        #每个月的还款计划
        for m in range(1,new_debt.loanPeriod + 1):
            #每期应还的利息 = 剩下的本金 * 月利息                              #Decimal将他改成双精度类型
            interest = round((new_debt.repaymenMoney - mount_cost * (m-1)) * Decimal(mount_rate),2)
            #每期应还的总金额 = 每月的本金 + 每个月的利息
            total = float(round(interest + mount_cost,2))

            #创建每一期的还款计划对象
            repay_plan = Debtor_repay(claimsId=new_debt.id,
                                      receivableMoney=total,
                                      currentTerm=m,
                                      recordDate=datetime.now()
                                      )
            db.session.add(repay_plan)

class MyLoeanApply(Resource):
    '''我的借款列表'''
    def get(self):
        rp = RequestParser()

        rp.add_argument('curPage')  # 当前页
        rp.add_argument('perPage')  # 每页数量

        args = rp.parse_args()

        cur_page = int(args.get('curPage'))
        per_page = int(args.get('perPage'))

        user_id = g.user_id
        loan_list = Loan.query.filter(Loan.lUid == user_id).paginate(cur_page,per_page,error_out=False)

        # 分页数据的序列化
        data = LoanPaginateSerializer(loan_list).to_dict()
        return {
            'msg': 'sucess',
            'data': data
        }






















